using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TerritoryGame.Application.Dtos;
using TerritoryGame.Application.Interfaces;
using TerritoryGame.Domain.Entities.App;
using TerritoryGame.Domain.Repositories;

namespace TerritoryGame.Application.Services
{
    public class AppUserLevelService : IAppUserLevelService
    {
        private readonly IRepository<UserLevel> _userLevelRepository;
        private readonly IRepository<User> _userRepository;

        public AppUserLevelService(IRepository<UserLevel> userLevelRepository, IRepository<User> userRepository)
        {
            _userLevelRepository = userLevelRepository;
            _userRepository = userRepository;
        }

        public async Task<UserLevelDto> GetUserLevelAsync(Guid userId)
        {
            // 通过UserId查询用户等级记录，而不是通过主键Id
            var userLevels = await _userLevelRepository.GetAllAsync();
            var userLevel = userLevels.FirstOrDefault(ul => ul.UserId == userId);
            
            if (userLevel == null)
            {
                // 如果用户等级记录不存在，创建一个新的
                var user = await _userRepository.GetByIdAsync(userId);
                if (user == null)
                    throw new ArgumentException("用户不存在");

                userLevel = await InitializeUserLevelAsync(userId, user.Username);
                return await GetUserLevelDtoAsync(userLevel);
            }

            return await GetUserLevelDtoAsync(userLevel);
        }

        public async Task<List<UserLevelDto>> GetAllUserLevelsAsync()
        {
            var userLevels = await _userLevelRepository.GetAllAsync();
            var users = await _userRepository.GetAllAsync();
            var userLookup = users.ToDictionary(u => u.Id, u => u.Username);

            var result = new List<UserLevelDto>();
            foreach (var ul in userLevels)
            {
                var experienceRequired = ul.GetExperienceRequiredForNextLevel();
                var levelProgress = ul.CurrentLevel >= 20 
                    ? 100.0  // 达到最高等级时显示100%进度
                    : (experienceRequired > 0
                        ? (double)ul.CurrentExperience / experienceRequired * 100
                        : 100);

                result.Add(new UserLevelDto
                {
                    UserId = ul.UserId,
                    Username = userLookup.TryGetValue(ul.UserId, out var name) ? name : string.Empty,
                    CurrentLevel = ul.CurrentLevel,
                    CurrentExperience = ul.CurrentExperience,
                    TotalExperience = ul.TotalExperience,
                    ExperienceRequiredForNextLevel = experienceRequired,
                    LevelProgress = Math.Round(levelProgress, 2),
                    CurrentTitle = ul.CurrentTitle,
                    UnlockedTitles = ul.UnlockedTitles,
                    LastLevelUpTime = ul.LastLevelUpTime
                });
            }

            return result;
        }

        public async Task<LevelUpResultDto> AddExperienceAsync(AddExperienceDto dto)
        {
            // 通过UserId查询用户等级记录，而不是通过ID
            var userLevels = await _userLevelRepository.GetAllAsync();
            var userLevel = userLevels.FirstOrDefault(ul => ul.UserId == dto.UserId);
            
            if (userLevel == null)
            {
                var user = await _userRepository.GetByIdAsync(dto.UserId);
                if (user == null)
                    throw new ArgumentException("用户不存在");

                userLevel = await InitializeUserLevelAsync(dto.UserId, user.Username);
            }

            var oldLevel = userLevel.CurrentLevel;
            var oldTitle = userLevel.CurrentTitle;
            
            var leveledUp = userLevel.AddExperience(dto.Experience);
            
            await _userLevelRepository.UpdateAsync(userLevel);

            return new LevelUpResultDto
            {
                LeveledUp = leveledUp,
                NewLevel = userLevel.CurrentLevel,
                NewTitle = leveledUp && userLevel.CurrentTitle != oldTitle ? userLevel.CurrentTitle : null,
                ExperienceGained = dto.Experience,
                Message = leveledUp 
                    ? $"恭喜升级到 {userLevel.CurrentLevel} 级！" + 
                      (userLevel.CurrentTitle != oldTitle ? $" 获得新称号：{userLevel.CurrentTitle}" : "")
                    : userLevel.CurrentLevel >= 20 
                        ? $"已达到最高等级20级！继续获得 {dto.Experience} 经验值，总经验值：{userLevel.TotalExperience}"
                        : $"获得 {dto.Experience} 经验值"
            };
        }

        public async Task<bool> ChangeTitleAsync(ChangeTitleDto dto)
        {
            // 通过UserId查询用户等级记录，而不是通过ID
            var userLevels = await _userLevelRepository.GetAllAsync();
            var userLevel = userLevels.FirstOrDefault(ul => ul.UserId == dto.UserId);
            
            if (userLevel == null)
                return false;

            // 检查用户是否已解锁该称号
            if (!userLevel.UnlockedTitles.Contains(dto.NewTitle))
                return false;

            userLevel.CurrentTitle = dto.NewTitle;
            await _userLevelRepository.UpdateAsync(userLevel);
            return true;
        }

        public async Task<List<TitleInfoDto>> GetUserTitlesAsync(Guid userId)
        {
            // 通过UserId查询用户等级记录，而不是通过主键Id
            var userLevels = await _userLevelRepository.GetAllAsync();
            var userLevel = userLevels.FirstOrDefault(ul => ul.UserId == userId);
            if (userLevel == null)
            {
                // 如果用户等级记录不存在，创建一个新的
                var user = await _userRepository.GetByIdAsync(userId);
                if (user == null)
                    throw new ArgumentException("用户不存在");

                userLevel = await InitializeUserLevelAsync(userId, user.Username);
            }

            var allTitles = UserLevel.GetAllTitles();
            var unlockedTitles = userLevel.UnlockedTitles;

            return allTitles.Select(title => new TitleInfoDto
            {
                Title = title,
                RequiredLevel = GetRequiredLevelForTitle(title),
                IsUnlocked = unlockedTitles.Contains(title),
                Description = GetTitleDescription(title)
            }).ToList();
        }

        public async Task<List<TitleInfoDto>> GetAllTitlesAsync()
        {
            var allTitles = UserLevel.GetAllTitles();
            return allTitles.Select(title => new TitleInfoDto
            {
                Title = title,
                RequiredLevel = GetRequiredLevelForTitle(title),
                IsUnlocked = false,
                Description = GetTitleDescription(title)
            }).ToList();
        }

        private async Task<UserLevel> InitializeUserLevelAsync(Guid userId, string username)
        {
            try
            {
                var userLevel = new UserLevel
                {
                    Id = Guid.NewGuid(), // 确保设置ID
                    UserId = userId,
                    CurrentLevel = 1,
                    CurrentExperience = 0,
                    TotalExperience = 0,
                    CurrentTitle = "墨痕初绽",
                    UnlockedTitles = new List<string> { "墨痕初绽" },
                    LastLevelUpTime = DateTime.UtcNow,
                    IsActive = true,
                    IsDeleted = false,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                await _userLevelRepository.CreateAsync(userLevel);
                return userLevel;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"创建用户等级记录失败: {ex.Message}", ex);
            }
        }

        private async Task<UserLevelDto> GetUserLevelDtoAsync(UserLevel userLevel)
        {
            var experienceRequired = userLevel.GetExperienceRequiredForNextLevel();
            var levelProgress = userLevel.CurrentLevel >= 20 
                ? 100.0  // 达到最高等级时显示100%进度
                : (experienceRequired > 0 
                    ? (double)userLevel.CurrentExperience / experienceRequired * 100 
                    : 100);

            return new UserLevelDto
            {
                UserId = userLevel.UserId,
                Username = userLevel.User?.Username ?? "",
                CurrentLevel = userLevel.CurrentLevel,
                CurrentExperience = userLevel.CurrentExperience,
                TotalExperience = userLevel.TotalExperience,
                ExperienceRequiredForNextLevel = experienceRequired,
                LevelProgress = Math.Round(levelProgress, 2),
                CurrentTitle = userLevel.CurrentTitle,
                UnlockedTitles = userLevel.UnlockedTitles,
                LastLevelUpTime = userLevel.LastLevelUpTime
            };
        }

        private int GetRequiredLevelForTitle(string title)
        {
            return title switch
            {
                "墨痕初绽" => 1,
                "玄疆漫步" => 5,
                "万象染境" => 10,
                "永夜封疆" => 15,
                "无界墨尊" => 20,
                _ => 1
            };
        }

        private string GetTitleDescription(string title)
        {
            return title switch
            {
                "墨痕初绽" => "初窥门径，落笔见微光，如新墨初染宣纸",
                "玄疆漫步" => "从容游走于版图，步伐如踏玄机之境，初显掌控力",
                "万象染境" => "挥墨成势，所涂之处自成小世界，技法已融自然万象",
                "永夜封疆" => "领地固若永夜，幽邃不可侵，墨色所覆即永恒黑夜",
                "无界墨尊" => "突破疆域桎梏，墨染随心无界，如天工执笔定乾坤",
                _ => "未知称号"
            };
        }
    }
}
